﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Security;

namespace PSE.ProcessManager.Common.Gateway
{
    /// <summary>
    /// Classe de hospedagem do serviço de comunicação.
    /// </summary>
    public class Listener
    {

        #region Propriedades

        private static string _namedPipeBaseAddress = "net.pipe://localhost/Listener/{0}";

        ServiceHost _host = null;
        ListenerService _listenerService = new ListenerService();
        Uri[] _baseAddresses;

        #endregion

        #region Events

        ServiceEvents.MessageReceived onReceiveMessage;
        /// <summary>
        /// Evento disparado ao receber uma mensagem.
        /// </summary>
        public ServiceEvents.MessageReceived OnReceiveMessage
        {
            get
            {
                return onReceiveMessage;
            }
            set
            {
                onReceiveMessage = value;
                //if (_listenerService != null)
                //    _listenerService.OnReceiveMessage = value;
                ListenerService.OnReceiveMessage = value;
            }
        }

        ServiceEvents.ClientConnected onConnect;
        /// <summary>
        /// Evento disparado ao receber uma mensagem.
        /// </summary>
        public ServiceEvents.ClientConnected OnConnect
        {
            get
            {
                return onConnect;
            }
            set
            {
                onConnect = value;
                //if (_listenerService != null)
                //    _listenerService.OnConnect = value;
                ListenerService.OnConnect = value;
            }
        }


        ServiceEvents.ClientDisconnected onDisconnect;
        /// <summary>
        /// Evento disparado ao receber uma mensagem.
        /// </summary>
        public ServiceEvents.ClientDisconnected OnDisconnect
        {
            get
            {
                return onDisconnect;
            }
            set
            {
                onDisconnect = value;
                //if (_listenerService != null)
                //    _listenerService.OnDisconnect = value;
                ListenerService.OnDisconnect = value;
            }
        }

        public ServiceEvents.IsProcessRunning IsProcessRunning
        {
            get
            {
                return ListenerService.IsProcessRunning;
            }
            set
            {
                ListenerService.IsProcessRunning = value;
            }
        }

        public ServiceEvents.RetrievedLogList OnRetrieveLogList
        {
            get
            {
                return ListenerService.OnRetrieveLogList;
            }
            set
            {
                ListenerService.OnRetrieveLogList = value;
            }
        }

        public ServiceEvents.RetrievedLastProcessLog OnRetrieveLastProcessLog
        {
            get
            {
                return ListenerService.OnRetrieveLastProcessLog;
            }
            set
            {
                ListenerService.OnRetrieveLastProcessLog = value;
            }
        }

        #endregion

        /// <summary>
        /// Fecha o channel do serviço Listener.
        /// </summary>
        public void Close()
        {
            if (_host != null)
                _host.Close();
        }


        /// <summary>
        /// Abre o channel do serviço Listener
        /// </summary>
        /// <param name="address">endereço utilizado pelo serviço</param>
        /// <param name="protocol">Protocolo de comunicação</param>
        public void Open(string address, Protocol protocol)
        {
            switch (protocol)
            {
                case Protocol.TCP:
                    _host = new ServiceHost(typeof(ListenerService));
                    break;
                case Protocol.NamedPipe:
                    _baseAddresses = new Uri[] { new Uri(string.Format(_namedPipeBaseAddress, address)) };
                    _host = new ServiceHost(typeof(ListenerService), _baseAddresses);
                    _host.AddServiceEndpoint(typeof(IListenerService), CreateProcessNamedPipeBinding(), ""); 
                    break;
                default:
                    break;
            }

            //Habilitação do Metadata.
            //_host.Description.Behaviors.Add(new ServiceMetadataBehavior());
            //_host.AddServiceEndpoint(typeof(IMetadataExchange), new NetNamedPipeBinding(), "mex");

            _host.Open();
        }

        private Binding CreateProcessNamedPipeBinding()
        {
            //Definição do protocolo de transporte do Binding
            NamedPipeTransportBindingElement namePipeTransport = new NamedPipeTransportBindingElement();

            namePipeTransport.MaxBufferPoolSize = 122880;
            namePipeTransport.MaxBufferSize = Int32.MaxValue;
            namePipeTransport.MaxReceivedMessageSize = Int32.MaxValue;
            namePipeTransport.ConnectionBufferSize = 122880;

            BinaryMessageEncodingBindingElement messageEncoding = new BinaryMessageEncodingBindingElement();

            return new CustomBinding(messageEncoding, namePipeTransport);
        }     
    }
}
